#pragma once

#include "iocp.h"
#include "BiDirectionMap.h"

struct ListCtrlUpdate {
	enum Type {INSERT, REMOVE};
	Type type;
	IOCP::ClientID cid;
	sockaddr_in addr;
};

class SwitchCore
{
public:
	SwitchCore();
	~SwitchCore();

	std::mutex mutex;
	std::atomic<IOCP::ClientID> hotCid = 0;
	std::queue<ListCtrlUpdate> eventQueue;
	std::queue<std::vector<char>> sendQueue;
	std::queue<std::vector<char>> recvQueue;

	void start();
	void stop();

	void EnableRecvSouthShow(bool enable);
	void EnableSendSouthShow(bool enable);

private:
	void WorkerThread();

	void OnNorthClientData(IOCP::ClientID, const std::vector<char>&);
	void OnSouthClientConnect(IOCP::ServerID, IOCP::ClientID, sockaddr_in);
	void OnSouthClientData(IOCP::ServerID, IOCP::ClientID, sockaddr_in, const std::vector<char>&);
	void OnSouthClientDisconnect(IOCP::ServerID, IOCP::ClientID, sockaddr_in);

	IOCP::IOCPTcpServer south;
	IOCP::IOCPUdpClient north;
	IOCP::NETPORT northBasePort;
	IOCP::ThreadPool threadPool_;

	BiDirectionMap<IOCP::ClientID, IOCP::ClientID> m_map;
	std::atomic<bool> running{ false };

	bool showRcvSouthEnable = true;
	bool showSendSouthEnable = true;
};

